home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / src / xad_RPM.lha / RPM.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-13  |  7.1 KB  |  234 lines

  1. /* RPM Package Manager (RPM) extractor client for XAD.
  2.  * Copyright (C) 2000 Stuart Caie <kyzer@4u.net>
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  * 
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  * 
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */
  18.  
  19. /* RPM is the concatenation of two things - some tag-based headers, and
  20.  * an archive. The headers are stored in central databases on people's
  21.  * machines and places like rpmfind.net. The archive is a gzip compressed
  22.  * cpio archive. All this client does is skip past the headers and then
  23.  * pretend to be just like the gzip slave (as far as possible)
  24.  */
  25.  
  26. #include <libraries/xadmaster.h>
  27. #include <proto/xadmaster.h>
  28. #include <string.h>
  29.  
  30. #include "SDI_compiler.h"
  31. #include "ConvertE.c"
  32.  
  33. #ifndef XADMASTERFILE
  34. #define RPM_Client        FirstClient
  35. #define NEXTCLIENT        0
  36. UBYTE version[] = "$VER: RPM 1.2 (13.09.2000)";
  37. #endif
  38. #define RPM_VERSION     1
  39. #define RPM_REVISION    2
  40.  
  41. #define XADBASE REG(a6, struct xadMasterBase *xadMasterBase)
  42. #define SKIP(offset) if ((err = xadHookAccess(XADAC_INPUTSEEK, \
  43.   (ULONG)(offset), NULL, ai))) goto exit_handler
  44. #define SEEK(offset) SKIP((offset) - ai->xai_InPos)
  45. #define READ(buffer,length) if ((err = xadHookAccess(XADAC_READ, \
  46.   (ULONG)(length), (APTR)(buffer), ai))) goto exit_handler
  47. #define ALLOC(t,v,l) \
  48.   if (!((v) = (t) xadAllocVec((l),0))) ERROR(NOMEMORY)
  49. #define ALLOCOBJ(t,v,kind,tags) \
  50.   if (!((v) = (t) xadAllocObjectA((kind),(tags)))) ERROR(NOMEMORY)
  51. #define FREE(obj) xadFreeObjectA((obj),NULL)
  52. #define ERROR(error) do { err = XADERR_##error; goto exit_handler; } while (0)
  53.  
  54.  
  55. ASM(BOOL) RPM_RecogData(REG(d0, ULONG size), REG(a0, UBYTE *d), XADBASE) {
  56.   return (BOOL) (d[0]==0xED && d[1]==0xAB && d[2]==0xEE && d[3]==0xDB);
  57. }
  58.  
  59. static const STRPTR RPM_arch[] = {
  60.   ".i386", ".alpha", ".sparc", ".mips", ".ppc", ".m68k",
  61.   ".sgi", ".rs6000", "", ".sparc64", ".mips", ".arm"
  62. };
  63.  
  64. ASM(LONG) SAVEDS RPM_GetInfo(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  65.   UBYTE *buffer, *fname;
  66.   struct xadArchiveInfo *ai2 = NULL;
  67.   struct xadFileInfo *fi;
  68.   LONG err = XADERR_OK;
  69.   int version, namelen;
  70.  
  71.   struct TagItem filetags[]  = {
  72.     { XAD_OBJNAMESIZE, 0 },
  73.     { TAG_DONE, 0 }
  74.   };
  75.  
  76.   struct TagItem datetags[] = {
  77.     { XAD_DATECURRENTTIME, 1 },
  78.     { XAD_GETDATEXADDATE,  0 },
  79.     { TAG_DONE, 0 }
  80.   };
  81.  
  82.   struct TagItem tags[] = {
  83.     { XAD_INXADSTREAM, 0 },
  84.     { TAG_DONE, 0 },
  85.     { XAD_ARCHIVEINFO, 0 },
  86.     { TAG_DONE, 0 }
  87.   };
  88.  
  89.   tags[0].ti_Data = (ULONG) &tags[2];
  90.   tags[2].ti_Data = (ULONG) ai;
  91.  
  92.   ALLOC(UBYTE *, buffer, 96+80); /* buffer = 96 bytes buffer for reading */
  93.   fname = buffer + 96; /* fname = 80 bytes for final archive filename */
  94.  
  95.   /* read in the 'lead' of the RPM */
  96.   READ(buffer, 96);
  97.  
  98.   /* create the archive name */
  99.   strncpy(fname, (buffer[10]) ? buffer+10 : "unknown", 66);
  100.  
  101.   if (EndGetM16(buffer+6) == 1) strcat(fname, ".src");
  102.   else {
  103.     int arch = EndGetM16(buffer+8);
  104.     if (arch >= 1 && arch <= 12) strcat(fname, RPM_arch[arch-1]);
  105.   }
  106.   strcat(fname, ".cpio");
  107.  
  108.  
  109.   /* check file format version */
  110.   version = buffer[4]; /* we support versions 2-4 only */
  111.   if (version < 2 || version > 4) return XADERR_DATAFORMAT;
  112.  
  113.   /* check 'digital signature' version */
  114.   switch (EndGetM16(buffer+78)) {
  115.   case 0: /* no signature */
  116.     break;
  117.  
  118.   case 1: /* fixed size signature */
  119.     SKIP(256);
  120.     break;
  121.  
  122.   case 5: /* another 'header' for the sig */
  123.     READ(buffer, 8);
  124.     if (EndGetM32(buffer) != 0x8EADE801) return XADERR_DATAFORMAT;
  125.     /* read tag count and data area length, skip them and align to 8 bytes */
  126.     READ(buffer, 8);
  127.     SKIP(((16 * EndGetM32(buffer) + EndGetM32(buffer+4)) + 7) & -8);
  128.     break;
  129.  
  130.   default: /* other versions not supported */
  131.     return XADERR_DATAFORMAT;
  132.   }
  133.  
  134.   /* normal header */
  135.   if (version != 2) {
  136.     READ(buffer, 8);
  137.     if (EndGetM32(buffer) != 0x8EADE801) return XADERR_DATAFORMAT;
  138.   }
  139.   /* read tag count and data area length, skip them */
  140.   READ(buffer, 8);
  141.   SKIP(16 * EndGetM32(buffer) + EndGetM32(buffer+4));
  142.  
  143.  
  144.   /* NOW GENERATE THE FILEINFO */
  145.  
  146.   filetags[0].ti_Data = namelen = strlen(fname) + 1;
  147.   ALLOCOBJ(struct xadArchiveInfo *, ai2, XADOBJ_ARCHIVEINFO, NULL);
  148.   ALLOCOBJ(struct xadFileInfo *, fi, XADOBJ_FILEINFO, filetags);
  149.   ai->xai_FileInfo = fi;
  150.  
  151.   fi->xfi_EntryNumber = 1;
  152.   fi->xfi_Size        = fi->xfi_CrunchSize = ai->xai_InSize - ai->xai_InPos;
  153.   fi->xfi_DataPos     = ai->xai_InPos;
  154.   fi->xfi_Flags       = XADFIF_SEEKDATAPOS | XADFIF_NODATE;
  155.  
  156.   /* copy name */
  157.   xadCopyMem(fname, fi->xfi_FileName, namelen);
  158.  
  159.   /* fill in today's date */
  160.   datetags[1].ti_Data = (ULONG) &fi->xfi_Date;
  161.   xadConvertDatesA(datetags);
  162.   
  163.   /* call 'get info' on embedded archive for accurate filesizes */
  164.   if (!xadGetInfoA(ai2, tags)) {
  165.     struct xadFileInfo *fi2  = ai2->xai_FileInfo;
  166.     if (fi2 && !fi2->xfi_Next) {
  167.       /* get crunched and uncrunched size */
  168.       fi->xfi_Size = fi2->xfi_Size;
  169.       fi->xfi_CrunchSize = fi2->xfi_CrunchSize;
  170.  
  171.       /* copy the CRYPTED, NOUNCRUNCHSIZE and PARTIALFILE flags */
  172.       fi->xfi_Flags |= fi2->xfi_Flags &
  173.       (XADFIF_CRYPTED | XADFIF_NOUNCRUNCHSIZE | XADFIF_PARTIALFILE);
  174.     }
  175.     xadFreeInfo(ai2);
  176.   }
  177.  
  178. exit_handler:
  179.   if (ai2) FREE(ai2);
  180.   if (buffer) FREE(buffer);
  181.   return err;
  182. }
  183.  
  184. ASM(LONG) RPM_UnArchive(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  185.   struct xadArchiveInfo *ai2 = NULL;
  186.   struct TagItem tags[5];
  187.   LONG err, recog = 0;
  188.  
  189.   tags[0].ti_Tag  = XAD_ARCHIVEINFO;
  190.   tags[0].ti_Data = (ULONG) ai;
  191.   tags[2].ti_Tag  = XAD_INXADSTREAM;
  192.   tags[2].ti_Data = (ULONG) tags;
  193.   tags[1].ti_Tag  = tags[3].ti_Tag = TAG_DONE;
  194.  
  195.   ALLOCOBJ(struct xadArchiveInfo *, ai2, XADOBJ_ARCHIVEINFO, NULL);
  196.   if (!(err = xadGetInfoA(ai2, &tags[2]))) {
  197.     struct xadFileInfo *fi2  = ai2->xai_FileInfo;
  198.     if (fi2 && !fi2->xfi_Next) {
  199.       recog = 1;
  200.  
  201.       tags[2].ti_Tag  = XAD_OUTXADSTREAM; /* ti_Data is still &arcinfo tag */
  202.       tags[3].ti_Tag  = XAD_ENTRYNUMBER;
  203.       tags[3].ti_Data = ai2->xai_FileInfo->xfi_EntryNumber;
  204.       tags[4].ti_Tag  = TAG_DONE;
  205.  
  206.       /* extract the first file */
  207.       err = xadFileUnArcA(ai2, &tags[2]);
  208.     }
  209.     else err = XADERR_DATAFORMAT;
  210.   }
  211.   xadFreeInfo(ai2);
  212.  
  213.   /* if an error occured in 'extracting', try again 'copying' */
  214.   if (err && recog) {
  215.     SEEK(ai->xai_CurFile->xfi_DataPos);
  216.     err = xadHookAccess(XADAC_COPY, ai->xai_CurFile->xfi_CrunchSize, NULL, ai);
  217.   }
  218.  
  219. exit_handler:
  220.   if (ai2) FREE(ai2);
  221.   return err;
  222. }
  223.  
  224.  
  225. const struct xadClient RPM_Client = {
  226.   NEXTCLIENT, XADCLIENT_VERSION, 8, RPM_VERSION, RPM_REVISION,
  227.   4, XADCF_FILEARCHIVER|XADCF_FREEFILEINFO,
  228.   0, "RPM",
  229.   (BOOL (*)()) RPM_RecogData,
  230.   (LONG (*)()) RPM_GetInfo,
  231.   (LONG (*)()) RPM_UnArchive,
  232.   NULL
  233. };
  234.